Render the API reference as Hugo content instead of embedding javadoc HTML - #5743
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a99a4541df
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Compared 151 screenshots: 151 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 181 screenshots: 181 matched. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3836132db4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cba3010b0b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Cloudflare Preview
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3b8faaea72
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1e93d67f47
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9de9dc6412
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a569253af9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Compared 160 screenshots: 160 matched. Benchmark Results
Detailed Performance Metrics
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bec5daf6d7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5064944016
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 087e1ff9bc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 91530e2fe4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 54e793bf2e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c167ef5120
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 391dfec806
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9ff935ea44
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Compared 148 screenshots: 148 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 144 screenshots: 144 matched. |
|
Compared 143 screenshots: 143 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 217 screenshots: 217 matched. |
|
Compared 149 screenshots: 149 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97a0855ce6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… HTML The website embedded the standard doclet's output by copying the generated tree into static/, rewriting every selector of javadoc's stylesheet to scope it under one div, and fetching deep pages into that div with a script that faked window.pathtoroot and re-enabled the search box javadoc had disabled. Dark mode lost that fight: a stylesheet that was never built to be themed cannot be themed from the outside, however many of its custom properties the site overrode with !important. maven/javadoc-hugo-doclet emits a page per type as a Hugo content file whose front matter is the API model, rendered by the site's own templates. The API pages are now the same pages as the rest of the site: same theme, same dark mode, same typography, same search. The standard doclet still runs alongside it to build javadocs.zip, so the two are renderings of one source of truth. Almost all of this codebase writes markdown documentation comments, and JDK 23 and later hand those to a doclet verbatim as DocTree.Kind.MARKDOWN, so comment bodies pass straight through to the goldmark that renders the rest of the site. No markdown library is involved; a second implementation could only disagree with the one that actually renders the page. The bigger win is structure the old pages never had. Parameters and return values are written here as markdown headings rather than as block tags -- 9068 "#### Parameters" against 816 "@PARAM", 7224 "#### Returns" against 1036 "@return" -- so the standard doclet renders them as an <h6> buried inside the description and no page carries a parameter table at all. MarkdownSections parses that convention back into structure, claiming only the six headings it knows and leaving "#### Threading", "#### Example" and the long tail of one-offs in the prose where the author put them. Compatibility is the risk, so it is checked rather than asserted. 304 distinct /javadoc/ URLs are linked from the site content and the developer guide, a fragment is part of the URL, and javadoc's fragment encoding has details that are easy to get wrong: type arguments erased away, arrays keeping brackets, varargs keeping an ellipsis in the declared spelling and losing it in the erasure, a type variable answering to both. check-javadoc-parity.py compares the two renderings of the same sources and now reports 2272 pages and 29583 fragments with nothing missing. It found three real defects while being written, including seven documented methods on com.codename1.ads.* that had no page anywhere because their superclass is package private. Also here: - Roughly 2200 links write the URL in directory form without the .html suffix, and every one of them 404'd, because the old script refused any path that did not end in .html. Each type page now carries that spelling as an alias. The alias is dropped where a package owns the same directory case-insensitively (com.codename1.ui.List against com.codename1.ui.list), which otherwise made the macOS build silently differ from the Linux one. - The site search now covers the API, matching identifiers and camel humps rather than going through Lunr, which is the wrong tool for 29000 member names. The index is grouped by type to keep it at 1.9MB rather than 9.7MB. - @SInCE and "#### Since" are dropped entirely, matching scripts/check-since-tags.sh, which already rejects them in sources. - check-guide-links.py no longer accepts links to javadoc's navigation pages. The site publishes no equivalent of index-all, allclasses-index, help-doc or the jQuery search page, so accepting those names would wave through a 404. serialized-form.html goes for a different reason: no Java serialization here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI, both mine: The parity gate scraped id attributes with a regex over the page text. The site is built with --minify and the minifier drops the quotes wherever HTML allows, so a quotes-only pattern saw almost no fragments on the minified side and reported 27784 of 29583 as missing on a build that was correct. Widening the pattern to accept unquoted values then matched Java source inside <pre> blocks: `int id = row.getInteger(0);` is not an attribute. It now uses HTMLParser, which knows the difference between markup and text. This passed locally only because the local build was not minified. check-guide-links.py then rejected https://www.codenameone.com/javadoc/ itself. javadoc_path_exists strips a "/javadoc/" prefix, but the caller strips the trailing slash first, so "/javadoc" kept the whole string as its path and was reported as a directory the generator never creates. That is a pre-existing bug that content/api.md was masking: a path found in the content tree never reaches this function, and deleting that page in favour of a generated overview exposed it. This also passed locally, because the generated content tree was still on disk -- the same contamination, twice. Both were re-verified with the generated tree moved aside and the site built minified. Review findings, all five real and all confirmed against the sources first: - See-also entries are markdown bullets, not @see tags, so nothing resolves them and the doclet has to parse the reference itself. It was passing the whole string to a type-only lookup, so 426 qualified references rendered unlinked, and stripping the parameter list off a local one picked the first member of that name -- #clear(int) linking to clear(). SeeAlsoRef now parses the reference properly, splitting trailing prose on parenthesis depth rather than on the first space. Red-teaming that turned up a second leg the review did not reach: roughly half the member references that name something real are inherited, and the resolver searched only the enclosing type. #CENTER on Label is Component.CENTER. With both fixed, 1376 entries link where 1303 did before the inheritance fix and far fewer before that; the 96 that remain are stale in the sources (Transform documents #setScale(), and declares only the two and three argument forms) or name types we do not ship. Those stay unlinked on purpose: sending a reader to an overload the author did not mean is worse than not linking. - @deprecated and @deprecated are independent, and only the tag was read. 23 files carry the annotation and com.codename1.ui.util.MutableResouce carries it with no tag at all, so it lost its deprecated marking entirely. - Constants went through String.valueOf, so DateFormatPatterns.RFC2822 rendered as bare text inside a code-formatted declaration rather than as a String literal, and a control character would have reached the page raw. - Type parameter documentation was read into doc.parameters and then never serialized. Worth being accurate about the scale: exactly one tag in the tree carries any text, VisionCameraView<T>, and the other two are empty. Fixed anyway, because discarding what an author wrote is the defect, not its size. Every fix has a test, and each was fault-injected to confirm it fails without the fix. 45 tests, and the parity gate is green against the minified build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…arkdown Two shapes the reference parser did not handle, found by looking at what was still unlinked after the review fixes rather than by waiting for the next round. Six entries wrap the reference in backticks -- `com.codename1.router.PopGuard`, `#translate(int, int)` -- which is how a reference is written everywhere else in a markdown comment. A backtick is not a Java identifier start, so the whole entry fell through to prose and rendered with its backticks showing. All six name something we publish. Nine entries are markdown links, all of them to MDN. Those were wrapped in a code span, so they displayed as literal [text](url). Non-reference entries are now flagged and rendered through the same markdown pipeline as the surrounding prose. See also entries now resolve to 1382 links, 13 prose or markdown, and 77 unresolved. The remainder are stale in the sources -- Transform documents #setScale() and declares only the two and three argument forms -- or name types we do not ship, such as net.miginfocom.layout.UnitValue. Both stay unlinked on purpose. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Found by building the site without --quiet, which is how the warning had gone unseen: goldmark renders with unsafe = false, so raw HTML in a comment body is dropped rather than rendered, and the only sign is one WARN line per page. 13 of the 2024 core sources still carry some, and what disappeared included the whole list of tuning values in box2d's Settings. That is content this PR deleted, since the pages it replaces rendered it. Turning goldmark's unsafe on is not the fix, and not only because it would change how 45 pages of existing blog content render. Half of this HTML is not markup: com.codename1.util.regex.RE documents a substitution string as <a href="$0">$0</a>, and PushBuilder writes <metadata>;<body> to mean one value followed by another. Rendering those is exactly how the standard pages lose them -- the browser eats <metadata> as an unknown element and shows a bare semicolon. So the two cases are separated. A structural tag with no attributes becomes its markdown equivalent, which is 129 of the 140 tags in the API and renders them properly; a heading is levelled down so a comment cannot outrank the page around it. Everything else is escaped and therefore visible exactly as written, which is better than the old pipeline, which dropped it, and better than the standard doclet, which mangles it. Fenced blocks and code spans are copied through untouched. Two of the tests caught the converter over-reaching while it was being written: a bare "<" in "a < b" is arithmetic and must not be escaped, and "</br>" is written as often as "<br>" and means the same single break. Raw HTML omitted on API pages is now 0, where it was 13. Also records why the site marks 299 more members deprecated than the standard pages do. That looked like an inheritance leak and was worth checking rather than assuming: every one of the 299 carries deprecation text from a "#### Deprecated" section the standard doclet cannot see, and none is an undocumented override picking the flag up from its parent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…vacuous The validation step I added grepped for id="createImage(byte[],int,int)" and failed on a build that was correct. The site is built with --minify and the minifier drops attribute quotes wherever HTML allows, so that page really does carry id=createImage(byte[],int,int) with none at all. This is the third time the same assumption has cost a red build here, after the parity gate's own id pattern and a local check I wrote while verifying it. The grep is worth keeping rather than deleting as a duplicate of the parity gate, because it is a canary for that gate: a comparison that ends up comparing nothing reports nothing missing, and reads exactly like success. But relying on a canary to notice that is backwards, so the gate now refuses to pass on a comparison smaller than 1000 pages or 10000 fragments. The real tree is 2272 and 29580, so the floors only trip when one side failed to generate or the parser stopped recognising anything -- which is precisely what the quotes-only pattern did, silently, on the side that was passing. Verified both ways: the floors leave a normal run untouched, and a run against a single-page tree now exits 1 instead of reporting success. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…them exposed
- Constructors were listed as <init>(String). getSimpleName() answers the JVM's
name for a constructor, and both the summary and the detail rendered it
straight, on every class page with a constructor and in the search index too.
The anchor keeps that spelling, because javadoc's fragment really is <init>().
- {@inheritdoc} written inside a "#### Returns" section was published literally.
The marker makes doc.returns non-null, and the inheritance step only filled in
a null, so BubbleTransition.copy and FlipTransition.copy showed the marker
where the parent's text belonged. Parameters had the same hole.
- A member promoted off a package private supertype resolved its See-also
references against the type that declares it, which by definition has no page.
CStringBuilder.capacity linked #ensureCapacity and #length into
/javadoc/com/codename1/util/AbstractStringBuilder.html, a file the generator
deliberately never writes. Both anchors are on CStringBuilder's own page.
- Interface pages claimed "Implements Iterable<E>" for "Collection<E> extends
Iterable<E>". getInterfaces() returns superinterfaces for an interface; only a
class implements.
- A Throws section naming java.io.IOException where the signature declares the
imported IOException produced two rows for one exception, one with prose and
one without. Matched on the simple name as well as the written one.
- The search index scanned the type's own elements while the page renders
promoted ones too, so InterstitialAd was searchable by its constructor alone
even though its page shows load(), isLoaded() and show(). It now indexes the
same list the page renders; searchable members go from 29247 to 29336.
Verifying the {@inheritdoc} fix surfaced something bigger behind it. Transition
documents its parameter as "- `reverse`: @PARAM reverse creates a new transition
instance": the name is given twice, once as the bullet and again as a tag the
markdown no longer needs. That is 1157 bullets across 184 files, and the
standard pages show it verbatim too, because to javadoc it is prose. Fixing 184
sources is a content sweep and does not belong in a rendering change, so the tag
is dropped at render time instead -- conservatively, only when it names the same
thing the bullet does, so a description that genuinely opens with an at-sign
survives.
53 tests. Parity green at 2272 pages and 29580 fragments.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codex's promoted-member finding was one instance of a class this PR can produce
and the parity gate cannot see: the generator mints these addresses itself
rather than copying them, so it can invent a link that resolves to nothing while
still reproducing every address javadoc publishes. So the whole tree is now
walked and every /javadoc/ link checked against the pages and ids that exist --
82634 fragment links across 4367 pages.
It found 13, in two kinds.
urlOf never checked whether the member it resolved is one the page renders. The
generator runs javadoc with -protected, so a {@link #position} landing on the
private field that com.codename1.maps.MarkerOptions declares beside a public
method of the same name produced a link to an id that was never written. Eleven
links, all to private members.
The visibility check has to read modifiers rather than documentation. Asking
DocReader made the generation die with a StackOverflowError, because reading an
element renders its comment, rendering resolves the links in it, and resolving a
link calls back into urlOf: two elements referring to each other is enough.
@hidden is now read straight off the block tags, which renders nothing.
The other kind was a constructor. A markdown link destination treats angle
brackets as a delimiter of its own, so [x](/p/T.html#<init>(int)) came out
mangled and the one link on the site pointing at a constructor from inside a
comment arrived as <init>. Angle brackets are percent encoded in a
destination now; parentheses are left alone, because they are balanced in every
signature javadoc emits and CommonMark allows balanced parentheses there.
Zero dead links remain. Both halves of the gate were fault-injected separately:
breaking an id fails the parity half, and pointing an href at a missing id fails
the link half with parity still passing. The probes assert their own edit landed,
after one of them silently patched nothing and reported success.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- A run of five backticks that opens and closes on one line is an inline code
span, not a fence: a backtick fence's info string may not contain a backtick.
Reading it as an opener left the parser inside a fence for the rest of the
comment, so LocalNotification.setAlertSound never saw its "#### Parameters"
heading and the parameter was published with no documentation at all while the
heading sat stranded in the description.
- Annotation elements were rendered without their defaults, so IntentParam's
required() and AppIntent's timeoutSeconds() read as required when they are
not. An array default arrives as a list of AnnotationValue and needs writing
as Java would write it: "String[] options() default {}" is {}, not a list's
toString.
- A See-also overload was accepted on argument count once the exact identifier
missed, which is how Vector#remove(Object) resolved to remove(int) and
Arrays#sort(Object[], int, int) to the byte[] overload. That is the failure
this code already refuses elsewhere on the grounds that a wrong link is worse
than none, and it was doing it anyway. Types are compared by simple name now,
so an imported spelling still matches a qualified one, and a reference that
matches no overload stays unlinked.
- Inherited fields were never listed. The collector walked methods only, so
Label showed none of Component's constants -- CENTER, TOP, the cursor values --
even though this same page links references to them. Fields now get the block
javadoc gives them, beside the methods one.
- A summary ended at the first full stop followed by a space without noticing
code spans, so JSONWriter.ArrayBuilder was cut mid span at
"Fluent builder for `[ ..., ..., ..." and rendered as malformed markup on its
package page and in search. Sentence detection and the hard length cap both
keep spans balanced now.
67 tests. Parity green at 2272 pages and 29580 fragments, every one of the 87386
internal links resolves, and no API page loses raw HTML.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…efaults Two of these are the same defect in two places: a simple name was resolved by scanning the whole API and taking the first match, which is not an answer when the name is ambiguous. java.text.Format.parseObject declares java.text.ParseException and documents it as "ParseException", and the Throws row linked com.codename1.l10n.ParseException. The method's own throws clause decides now. java.util.AbstractList referring to "List#size" was sent to com.codename1.ui.List. The package the reference was written in decides now, which is what the language does with an unqualified name. Worth noting how this one surfaced: the link resolved, so the internal-link gate added in the previous commit could not see it. A gate that checks whether a link points at something real cannot check whether it points at the right thing, and codex said so explicitly. Fixing it also recovered links that were being lost -- "List#isEmpty" had no target at all, because the widget it resolved to has no such method. Third, Infinity and NaN have no literal spelling in Java, so toString gives text no source could contain: Numeric.min() and Numeric.max() rendered as -Infinity and Infinity. They are written as the expressions that produce them now, the way javadoc writes them. The first version of the same-package test passed with the fix removed, because a global scan happened to reach the right type first. It now puts a type of the same name in two packages with a referrer in each, so no iteration order can satisfy both assertions; re-verified by removing the fix and watching it fail. 69 tests. Parity green, all 87388 internal links resolve. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- "Parameters", "Returns" and "Throws" are member concepts, and claiming them anywhere else destroyed content. com.codename1.db documents how the database binds its arguments under a "Parameters" heading; the parser lifted the whole section out of the package page and then dropped it, because a package page has nowhere to put a parameter table. Those three headings are now structural only on a method or constructor. Deprecation and See-also stay structural everywhere, because a package can be deprecated and does refer to other API. - And com.codename1.ui.layouts.mig is deprecated: its comment warns not to rely on the integration in production. DocReader lifted that out of the description and the package model had no field to put it in, so the warning was published nowhere at all. - types.directSupertypes() hands an interface java.lang.Object, which the language does not. Interface pages such as SuccessCallback claimed ten inherited Object methods, protected clone() among them. - The erased signature is not enough to tell two inherited methods apart once generics are substituted along a hierarchy: Enum.compareTo(E) erases to compareTo(java.lang.Enum) and Comparable.compareTo(T) to compareTo(java.lang.Object), so every enum page listed compareTo twice even though the first implements the second. Deduplication asks Elements.overrides now, bucketed by simple name so it only ever compares methods that could be the same one. 72 tests. Parity green, all 84019 internal links resolve, no API page loses raw HTML. Generation goes from roughly 5s to 8s for the override checks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- An interface's known subtypes are transitive in the standard reference, and
listing only direct children hid most of what a reader is looking for:
java.util.Collection named four types where the standard page names Deque,
NavigableSet, ArrayList, Vector and the rest. Classes keep direct children,
which is what javadoc's "Direct Known Subclasses" means.
- A public nested type is addressable through a subtype and javadoc lists it, so
Dialog omitted Form.TabIterator entirely. Nested types now get the inherited
block that fields and methods already had.
- The signature partial stopped at the closing parenthesis, so a declared throws
clause never appeared: AsyncResource.await read as though it threw nothing.
Only the declared exceptions go in the declaration, not the ones a comment
documented without declaring; those stay in the prose where they belong.
- Mapping <pre> to blank lines kept the text and lost the formatting that was
the point of the tag. CommerceManager's multi-line usage example collapsed
into a paragraph, because two-space indentation is not a markdown code block.
<pre> becomes a fenced block now, and a multi-line {@code} becomes one too,
which is what makes the <pre>{@code ...}</pre> idiom work: it arrives already
fenced and is passed through rather than wrapped again, since a fence inside a
fence is not a code block.
74 tests. Parity green, all 84019 internal links resolve, no API page loses raw
HTML.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Type declarations hid their modifiers. The model carried "public abstract" and the heading rendered "class Layout", so whether a type can be instantiated or subclassed was not shown anywhere on its page. - An override with no comment of its own takes its parent's whole documentation, and the parent named the parameters as it saw fit. GridBagLayout.addLayoutComponent calls its first parameter "constraints" where Layout calls it "value", so looking the text up under the child's name found nothing and the page printed "Not documented" beside it while the other two inherited normally. Inherited parameter text is paired by position now, on both inheritance paths. Worth recording how that one went: the first fix was written into resolveInheritDoc, which handles a comment that asks to inherit. It made no difference, because a method with no comment at all never reaches that method -- it returns the parent's doc wholesale much earlier. Only checking the real output showed it, and the fix belongs in both places. - A Throws bullet may name its exception with a markdown reference link, which is how a JEP 467 comment names any Java element. NdefMessage.parse does, and the bullet produced a nameless row holding the prose while the declared exception was listed again with nothing against it. Both new tests were vacuous when first written and were rebuilt until they failed with the fix removed. The parameter one gave the override a doc comment, which sends it down the path that was already correct rather than the one that was broken. 76 tests. Parity green, all 84019 internal links resolve, no API page loses raw HTML. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… defects The first two matter more than their P2 badges suggest. Map.of rejects a null value, and the type-parameter row passed one, so the whole generation died with a NullPointerException the moment any method documented a type parameter. Nothing in the framework does today -- the three such tags in the tree are all on types -- which is the only reason this was not already a broken build rather than a latent one. Reproduced with a three-line class before fixing it. And the parity gate had a blind spot I put there. Its chrome pattern matched any identifier merely STARTING with class, constructor, method, field, property, enum-constant or annotation, so methodType(...), fieldSubmitted(...), propertyChanged(...), annotationType() and propertyNames() -- 18 real member anchors -- were excluded from the comparison, and a regression in exactly those published URLs would have passed. The pattern is anchored end to end now, which raised the compared fragments from 29580 to 29595 and surfaced one more piece of genuine chrome (the class-summary table on package pages) to name explicitly. The rest: - Default link labels dropped the enclosing type, because the test was whether the character before a dot is lower case and ordinary names end in one: Pose.Landmark.getName() was shortened to Landmark.getName(). The type name starts at the first segment beginning with a capital. - An enum-valued annotation default rendered as the bare constant, so DesktopBuild read "default DEFAULT" with no clue which enum. The build-hint annotations are full of enums that each define a DEFAULT. - A Throws section holding prose rather than a list produced a blank exception row with the text stranded beside an empty label. A section with no bullet in it is prose and stays where the author put it. That last fix was too aggressive when first written -- it keyed on whether a name could be parsed, which discarded bullets whose text defeats the parser -- and two existing tests caught it. The rule is the presence of a bullet, not the success of the name parse. One older test asserted the previous behaviour for a bullet-less body on a method; that assertion was obsolete rather than the fix wrong, so it now contrasts on the element kind it was actually about. 78 tests. Parity green at 29595 fragments, all 84019 internal links resolve, no blank exception rows anywhere, and round five's package-section fix still holds. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…vered - The repository writes its own @warning tag, 22 of them, and every one was being dropped on the floor because the block-tag switch had no case for it and its default branch looked only for @hidden. They are safety notes: Body.createFixture warns that the function is locked during callbacks. The default branch now names the tags that are deliberately not published -- author, version, since, and the serial family -- and keeps the text of anything else. @warning gets a callout of its own. - Walking the inheritance chain asked each element for its superclass, which answers with the type variables as declared, so every substitution above the first was lost: com.codename1.io.Properties extends HashMap<String, String> and its ancestry read AbstractMap<K, V>, naming variables that mean nothing there. The walk steps through the mirror now. - Annotations on a type declaration were never published, so AppIntent showed neither @retention(CLASS) nor @target(METHOD) -- the two things that say how an annotation may be used at all. Only annotations that ask to be documented are shown, which is the rule javadoc follows. - Every full stop followed by a space ended the summary, including the one in "e.g.", so AdError.CODE_INVALID_REQUEST was cut mid-parenthesis in the package table and in search. Abbreviations and unbalanced parentheses are both accounted for now. The generics test was vacuous when first written: its middle class spelled its parent concretely, so no substitution could be lost and it passed with the fix removed. A substitution only goes missing when the intermediate class is itself generic, which is the HashMap<K, V> extends AbstractMap<K, V> shape, so the fixture is that now. The other two were fault-injected as written. 81 tests. Parity green at 29595 fragments, all 84021 internal links resolve, no API page loses raw HTML, and all 22 warnings reach the page. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d spot - The subtype graph stopped at any parent without a page, so a package private intermediate cut the branch off entirely: AbstractVisionAnalyzer sits between VisionAnalyzer and all seven of its public implementations, and every one was invisible from the interface's page. An unpublished type is walked through now rather than treated as the end of the line. - Type relationships read only the declaration, so a class that inherits its interfaces rather than declaring them showed none at all. CheckBox was published with an empty list while it really carries ActionSource, Animation, Editable, IconHolder, ReleasableComponent, SelectableIconHolder, StyleListener and TextHolder. - Constructors promoted from an undocumented superclass were indexed for search, though constructors are not inherited and the page renders only its own: ComponentAnimation.UIMutation offered CompoundAnimation's two constructors, both pointing at <init> fragments that page does not have. - The last parameter of a varargs method is an array in the model, so search showed asList(T[]) for asList(T... array), and byte[][] for byte[]..., which says something different. 1198 labels carried the array spelling and none an ellipsis; there are 216 now. The third of those is a dead link the link gate structurally cannot see: it walks <a href> attributes and the search index is JSON. So the gate has a third pass over the index, checking that every entry lands on a page and an id that exist -- 31430 entries. Fault-injected by pointing one entry at a fragment that is not there. Two of the four tests needed rebuilding before they bit. The subtype one put a PUBLISHED class in the middle, where nothing can be lost, when the whole finding is about an unpublished one. The varargs fix had no test at all until the run started emitting a search index to assert against. 84 tests. Parity green at 29595 fragments, 84021 internal links and 31430 search entries all resolve. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The results list escapes what it is given rather than rendering it, which is right for a value that came out of a comment -- but the summary was still markdown, so 622 of the 2096 types displayed backticks, emphasis markers or a whole link destination to the reader. Searching for PiiScrubber offered "Default PII scrubber for `CrashProtection` uploads." with the backticks showing. The index carries plain text now: a link reduces to the words it was marking up, code spans and emphasis lose their delimiters. The page-side summaries stay markdown, because Hugo renders those. Two things turned up while checking the result, both the same shape as a bug fixed three rounds ago for code spans. The sentence scan could end inside a bold span, and the hard length cap could cut one open -- BrowserNavigationCallback opens with a bold note that runs past 240 characters. Backing out of the span is the wrong repair there, because the span starts at character zero and backing out leaves nothing, so the cut closes what it opened instead. Zero summaries are left with an unbalanced span, on either side. Worth recording one non-finding: WebMercator writes "tileSize * 2^zoom", which my first check flagged as stray emphasis. It is multiplication, the summary was always correct, and the detector was the thing that was wrong. It survives intact and there is a test saying so. 87 tests. Parity green at 29595 fragments, 84021 internal links and 31430 search entries all resolve, and reverting the fix puts all 622 back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Clicking any class on the preview left the site: the link went to /javadoc/com/codename1/ui/Label.html, and the reader ended up on www.codenameone.com. Reported against the deployed preview, and every gate here was green while it was broken. Cloudflare Pages will not serve a .html URL. Its own html_handling redirects /x.html to /x before an asset is considered -- confirmed against an empty project with no _redirects file at all, so this is the platform and not the site's configuration -- and the site's redirect table separately maps /*.html to /:splat/. The page published at the extension was therefore one nobody could reach: the .html spelling 301'd to the directory, the directory held the alias this PR added, and that alias carried an absolute production URL because Hugo builds aliases from baseURL. Hence the jump to the live site. Pages are published at the directory URL now, and the javadoc spelling lands on them by the redirect that was already breaking it. Verified end to end against the Pages runtime: Label.html, Label/, package-summary.html, package-summary/ and /javadoc/ all return 200 with the right title and never leave the deployment. The alias is gone with it, so nothing points at another domain. The package directory loses its alias too, deliberately: an index.html there is the same file as the com.codename1.ui.List type page on a case insensitive filesystem, and one silently overwrote the other. Why nothing caught it, and what does now: The parity gate compares files on disk and the link gate reads href attributes. Both are blind to what a server does with a request, and a redirect is exactly that. scripts/website/check-javadoc-urls.sh asks the Pages runtime instead -- every URL shape a reader can arrive by, asserting 200, a real title, and that the final URL is still inside the deployment. Staging the old layout back makes it fail, which is the check that it would have caught this. Two of my own checks were wrong while I worked through it, both found by their own guards rather than by reading them. The parity gate filtered chrome before normalising Hugo's index.html names, so it discarded all 2272 pages and compared nothing -- the anti-vacuity floor added two rounds ago is what reported it. The search pass did not expand a directory URL to its index.html and called all 2096 entries broken. Verified on a case-sensitive volume, because this Mac's filesystem is not one and the List/list and Painter/painter pairs differ only by case. There they are distinct directories and all three passes are green: 2272 pages, 29595 fragments, 84021 links, 31430 search entries. 87 tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The biggest was not what it looked like from the outside. codex reported that AppIntent shows [IntentParam] unlinked while the standard pages link it, and it does -- but [IntentEntity], three lines away in the same comment, WAS linked. Both resolve identically at the DocTree level, which is what made it worth chasing rather than patching. Indexing was rendering the comments. collectType asked isHidden, isHidden went through DocReader, and reading an element there renders its whole comment -- which resolves the links in it, against a set of published types that is still being filled in, and then caches the result. A reference to a type reached later in the walk was frozen as an unlinked code span forever. It was an ordering accident, and it cost 1189 links across the API: 3295 before, 4484 after. @hidden is read straight off the block tags now, the way urlOf already had to. The other five: - A markdown autolink starts with a letter after the angle bracket, so the legacy-HTML converter claimed it as a tag and escaped it. Otp documents the key URI format that way and the page showed literal angle-bracketed text. CommonMark's rule is a scheme followed by a colon. - The plain-text search summary added last round stopped a link destination at its first ")", and a member URL ends in a signature: AdError arrived in the index as "AdListener.onFailedToLoad(AdError))". My regression, one round old, now scanned with balanced parentheses instead of matched. - A promoted member kept its declaration-local types, so PoseDetector rendered process as returning AsyncResource<T> though PoseDetector declares no T and the answer is AsyncResource<Pose>. Resolved through Types.asMemberOf, which fixes the parameters and the throws clause with it. - A package private implementation class was published in the hierarchy, where it cannot be named by a consumer and has no page. The standard doclet leaves it out -- PoseDetector's tree is Object then PoseDetector -- and now so does this, still walking through it so the substitution reaches the next visible ancestor. - Enum and annotation headings were not legal declarations: "public final enum" and "public abstract annotation". final is implicit on an enum, abstract on an annotation, and the keyword is @interface. 90 tests, the two unit-testable fixes fault-injected. Verified on a case-sensitive volume: 2272 pages, 29595 fragments, 84645 links, 31430 search entries, and every URL shape resolving on the Pages runtime. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Deprecation was being inherited onto overrides. Java does not inherit @deprecated and neither do the standard pages: ScaleImageLabel's setPreferredH and setPreferredW carry only @OverRide, and both were rendering a Deprecated banner with Component's prose under it. An undocumented override takes its parent's description, and the copy was taking the flag with it. This one is mine, from round seven. Round five had measured that every extra deprecation the site showed carried real text and none came from an override -- which was true when measured, and stopped being true two rounds later when whole-doc inheritance was added. A measurement is evidence about the moment it was taken. - Package private interfaces were published as part of the type's contract. GameView listed SpriteRenderer.Updatable and Ads listed CSSParserCallback, neither of which a consumer can name and neither of which has a page. Same defect the previous round fixed for superclasses; the traversal still goes through them so their public superinterfaces are still found. No interface without a page is listed anywhere now. - The framework writes @deprecated as a block tag UNDER a "#### Deprecated" heading, and anything after it -- "#### See also" and its bullets -- is inside the tag as far as the JDK is concerned. Storing that body whole put the heading inside the deprecation banner and dropped the references: CellRenderer and ImageDownloadService had no See-also at all and now have two and three. The test for the last one was vacuous as first written, because the fixture used a "#### Deprecated" heading, which the ordinary parser already splits. It only bites against a real @deprecated block tag, which is what the framework actually writes. 92 tests, both code fixes fault-injected. Case-sensitive build green on all three gate passes plus the Pages runtime: 2272 pages, 29595 fragments, 84653 links, 31430 search entries. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An enum constant is a VariableElement of kind ENUM_CONSTANT, so ElementFilter.fieldsIn returns it and it was being modelled as an ordinary field. BindAttr listed TEXT, UIID and the rest under Fields as "public static final BindAttr TEXT", which is how the model spells it and not how anyone writes or reads it. The standard reference gives them an enum-constant summary and detail and emits no field summary at all. 192 enums and 1136 constants across the API. The parity gate could not see this: an enum constant's fragment is its bare name either way, so every address was answered while the page was wrong. The same is true of most of what this review round has found -- presentation is not addressed by any of the three passes. The test was vacuous as first written. It asserted the enumConstants key exists, and that key is written either way, empty. What differs is which list the constants land in, so it asserts the field list is the empty one. 93 tests. Case-sensitive build green on all three gate passes and on the Pages runtime. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ff Object Two findings, plus the rebase that fixes the red build. The block-tag fix was made one tag too narrowly a round ago. A tag written underneath a heading of the same name swallows whatever follows it, and that is true of @return and @PARAM and @throws exactly as it was of @deprecated: 205 methods rendered a "#### Throws" heading and its bullet inside their Returns text and emitted no exception row, com.codename1.ui.CN.requestFullScreen among them. One helper now handles every tag with a body; the count is 0. directSupertypes() hands an interface java.lang.Object, which the language does not, so seeding the subtype graph from it made every interface a known subtype of Object: the Object page listed 1406, of which 314 were interfaces. Now 1089 and none. The filter has to run at every hop rather than at the seed -- HTMLCallback reaches Object through the package private CSSParserCallback and survived the first attempt. There is no unit test for the second one, deliberately. java.lang.Object comes from Ports/CLDC11 and cannot be in the doclet's own fixture, so the edge is never recorded there and the test I wrote passed with the fix removed. It is deleted rather than kept green, and the measurement is recorded in the code instead. CI was red on "Check cast semantics" for a reason that was not in this branch at all: master added an anonymous class earlier in AndroidImplementation, which renumbered the one the baseline pins from $46 to $47, and master updated the baseline while this branch was eight commits behind. Rebased; the check passes locally with 86 baselined and no new findings. 94 tests. Case-sensitive build green on all three passes and on the Pages runtime: 2273 pages, 29600 fragments, 84804 links, 31436 search entries. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
97a0855 to
73842e6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73842e6f50
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
ANNOTATION_TYPE is its own ElementKind and is not INTERFACE, so the interface-only tests added last round quietly excluded every annotation: 78 of them were still listed as known subtypes of Object, and their pages claimed to inherit clone(), wait(), getClass() and the rest, which an annotation interface does not. One predicate now answers that question and all five call sites use it. Object's known subtypes go from 1089 to 1011, with no annotation and no interface left among them. That exposed the rest of it. An annotation type has no supertypes worth publishing at all: it implicitly extends java.lang.annotation.Annotation, and the standard reference says so nowhere -- no superinterface line, no inherited members, no mention of Annotation anywhere on the page. Fixing only Object left AppIntent claiming four inherited methods from Annotation instead of ten from Object. It now claims none, which is what the standard page shows. Every supertype walk goes through the one filtered view now rather than calling directSupertypes itself, so a rule added in one of them cannot go missing from the other three. That was the actual defect behind this round and the last: the Object rule existed in allSupertypes and not in the subtype indexer, and then existed in both and not for annotations. 94 tests. Case-sensitive build green on all three passes and on the Pages runtime: 2273 pages, 29600 fragments, 83953 links, 31436 search entries. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 14a88cd55c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… and stop the parity scan dying on prose A package private interface can sit behind a documented class that implements it, and every descendant was then handed the interface's abstract methods as its own: GameSceneView declared "public abstract setup(GraphicsDevice)" and "frame(double)" though it is concrete and inherits GameView's implementations, which is what the standard page lists. The rule took three tries and the gate rejected all the wrong ones, which is worth recording because each was plausible: - Suppressing anything a documented supertype declares removed process() from all seven vision analysers. VisionAnalyzer only NAMES it; the implementation is on the package private AbstractVisionAnalyzer. - Suppressing on documented CLASSES only still removed flush(), getMaxSteps() and setStep(int) from ComponentAnimation.UIMutation, because ComponentAnimation declares them and the package private CompoundAnimation overrides them. - What actually distinguishes the cases is the promoted member itself. An abstract one shows a concrete class declaring something it does not declare. A concrete one IS the implementation and has to stay. Separately, the parity gate was reading pages with html.parser, which switches into raw-text mode on <title> and stops recognising markup until the matching close tag -- and documentation prose contains those. PushBuilder documents a payload as "<title>;<body>" with no close tag, so build(), getType() and isRichPush() went unseen and deleting those anchors would have passed. Across the standard tree the parser lost 1809 ids on 1150 pages; all but three were prose-heading noise the filters discard anyway, so the count checked barely moves, but the mechanism removes coverage wholesale from any page whose prose contains such a tag. Tags are found by scanning inside <...> now. Not a regex over the whole text, which was tried earlier and read Java source in a <pre> block, where "int id = row.getInteger(0);" is not an attribute. 94 tests. Case-sensitive build green on all three passes and on the Pages runtime: 2273 pages, 29603 fragments, 83953 links, 31434 search entries. The rewritten scan was fault-injected to confirm it still fails on a broken anchor. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a142351313
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…eating code spans as markup Three defects from the ninth review round, each with a test that fails without its fix. Imports decide an unqualified type name. The fallback was a scan for any documented type whose qualified name ends in that simple name, so the answer was iteration order. Two documented types are called Style -- com.codename1.ui.plaf.Style and the nested com.codename1.charts.compat .Paint.Style -- and Component reaching the right one was luck rather than rule. The compilation unit's imports are now consulted, and they shadow the package sibling, which is what JLS 6.4.1 says and what a reader of the file would assume. Over the real API this changes nothing today; it makes the outcome a rule instead of an accident. A see-also may spell a generic parameter by its erasure. The anchor already carried both aliases, so only the signature comparison was rejecting it: Collection#toArray(Object[]) against Set.toArray(T[]) and NavigableMap#higherEntry(Object) against TreeMap.higherEntry(K) both rendered as code with no link. A code span is literal text, so its brackets are not reference shorthand. Stripping them turned JSONWriter.ArrayBuilder's search summary from "Fluent builder for `[ ..., ..., ... ]`." into the confusing "Fluent builder for ..., ..., ... ." Each span is lifted out before the markup rewrites run and put back afterwards. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Why
The website embedded the standard doclet's output by copying the generated tree into
static/, rewriting every selector of javadoc's stylesheet to scope it under onediv, and fetching deep pages into that div with a script that fakedwindow.pathtorootand re-enabled the search box javadoc had disabled. Dark mode lost that fight: a stylesheet that was never built to be themed cannot be themed from the outside, however many of its custom properties the site overrode with!important.What
maven/javadoc-hugo-docletemits a page per type as a Hugo content file whose front matter is the API model, rendered by the site's own templates. The API pages are now the same pages as the rest of the site: same theme, same dark mode, same typography, same search. The standard doclet still runs alongside it to buildjavadocs.zip, so the two are renderings of one source of truth.Almost all of this codebase writes markdown documentation comments, and JDK 23 and later hand those to a doclet verbatim as
DocTree.Kind.MARKDOWN, so comment bodies pass straight through to the goldmark that renders the rest of the site. No markdown library is involved; a second implementation could only disagree with the one that actually renders the page.The bigger win is structure the old pages never had. Parameters and return values are written here as markdown headings rather than as block tags -- 9068
#### Parametersagainst 816@param, 7224#### Returnsagainst 1036@return-- so the standard doclet renders them as an<h6>buried inside the description and no page carries a parameter table at all.MarkdownSectionsparses that convention back into structure, claiming only the six headings it knows and leaving#### Threading,#### Exampleand the long tail of one-offs in the prose where the author put them.Compatibility is checked, not asserted
304 distinct
/javadoc/URLs are linked from the site content and the developer guide, a fragment is part of the URL, and javadoc's fragment encoding has details that are easy to get wrong: type arguments erased away, arrays keeping brackets, varargs keeping an ellipsis in the declared spelling and losing it in the erasure, a type variable answering to both.scripts/website/check-javadoc-parity.pycompares the two renderings of the same sources:It found three real defects while being written:
of(T... values)bothof(T...)andof(java.lang.Object[]); the ellipsis was being written into the erased form too, losing the second address.com.codename1.ads.*had no page anywhere. The same rule reaches through a documented type --CSSParserCallback's constants appear on bothHTMLCallbackandDefaultHTMLCallback.com.codename1.ui.List(class) againstcom.codename1.ui.list(package): the new directory aliasui/List/swallowed the package directory on macOS, silently correct on Linux CI. The alias is dropped where a package owns that directory.Both gates are fault-injected: reintroducing the varargs bug fails
dropsTheEllipsisFromAnErasedVarargs, and deleting a page plus mangling an anchor fails the parity script with exit 1.Also here
.htmlsuffix, and every one of them 404'd, because the old script refused any path that did not end in.html. Each type page now carries that spelling as an alias.@sinceand#### Sinceare dropped entirely, matchingscripts/check-since-tags.sh, which already rejects them in sources.check-guide-links.pyno longer accepts links to javadoc's navigation pages. The site publishes no equivalent ofindex-all,allclasses-index,help-docor the jQuery search page, so accepting those names would wave through a 404.serialized-form.htmlgoes for a different reason: no Java serialization here.Testing
.github/scripts/build_javadocs.shoutput: 2096 types, 2273 pages, generation ~4s, Hugo absorbs the extra pages in ~2s.check-guide-links.py,check-copyright-headers.shandcheck-control-characters.pyall clean over the branch range./search/.🤖 Generated with Claude Code